package com.xxx.util;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.druid.util.StringUtils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;

/**
 * JWT token 工具类
 * 
 * 
 * 
 */
public class JwtUtil {
	
	private static final Logger logger = LoggerFactory.getLogger(JwtUtil.class);

	public static final String USER_ID = "userId";		// 用户ID
	private static final String SECRET = "xxx@13579";  	// token秘钥，请勿泄露，且勿随便修改
	private static final int calendarInterval = 1440;	// token过期时间: 1440分钟

	/**
	 * JWT生成Token
	 * JWT构成: header, payload, signature
	 * @param userId 登录成功后用户userId, 参数userId不可传空
	 */
	public static String createToken(String userId) {
		logger.debug("enter method createToken(). userId:{}", userId);
		if(StringUtils.isEmpty(userId)) {
			return null;
		}
		
		Date issuedAt = new Date();
		Calendar nowTime = Calendar.getInstance();
		nowTime.add(Calendar.MINUTE, calendarInterval);
		Date expiresAt = nowTime.getTime();

		// header Map
		Map<String, Object> map = new HashMap<>();
		map.put("alg", "HS256");
		map.put("typ", "JWT");

		// create token
		String token = JWT.create()
				.withHeader(map) 					// header
				.withClaim(USER_ID, userId) 		// payload: userId
				.withIssuedAt(issuedAt) 			// issue time
				.withExpiresAt(expiresAt) 			// expired time
				.sign(Algorithm.HMAC256(SECRET)); 	// signature

		return token;
	}

	/**
	 * 解密Token
	 * 
	 * @param token
	 * @return
	 */
	public static Map<String, Claim> verifyToken(String token) {
		DecodedJWT jwt = null;
		try {
			JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
			jwt = verifier.verify(token);
		} catch (TokenExpiredException ex) {
			// token 校验失败, 抛出Token验证非法异常
			logger.error("verifyToken | the token:{} has expired. " + ex.getMessage(), token, ex);
			return null;
		} catch (Exception e) {
			// token 校验失败, 抛出Token验证非法异常
			logger.error("verifyToken | the token:{} happend exception" + e.getMessage(), token, e);
			return null;
		}
		return jwt.getClaims();
	}
	
	/**
	 * 从Claim里获取userId
	 * @param token
	 * @return userId
	 */
	public static String getUserIdFromClaim(Map<String, Claim> claims) {
		if(claims==null) {
			logger.error("getUserIdFromClaim | claims is null");
			return null;
		}
		
		Claim userId = claims.get(USER_ID);
		if (null==userId || StringUtils.isEmpty(userId.asString())) {
			// token 校验失败, 抛出token验证非法异常
			logger.error("getUserIdFromClaim | userId is empty.");
			return null;
		}
		return userId.asString();
	}
	
	/**
	 * 根据token获取userId
	 * @param token
	 * @return userId
	 */
	public static String getUserIdByToken(String token) {
		Map<String, Claim> claims = verifyToken(token);
		if(claims==null) {
			logger.error("getUserIdByToken | claims==null");
			return null;
		}
		
		Claim userId = claims.get(USER_ID);
		if (null==userId || StringUtils.isEmpty(userId.asString())) {
			// token 校验失败, 抛出token验证非法异常
			logger.error("getUserIdByToken | userId is empty.");
			return null;
		}
		return userId.asString();
	}
	
	public static void main(String[] args) {
//		String userId = "5613951143";
//		String token = createToken(userId);
//		System.out.println("token:" + token);
//		String token  = "1eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1Mzc1NzcxNzQsInVzZXJJZCI6IjU2MTM5NTExNDMiLCJpYXQiOjE1Mzc1NzY1NzR9.KAqgbuPx7fGfqpjKh3o600NU1pVZHerfqMwZ1g1M3ww";
//		String userId1 = getUserIdByToken(token);
//		System.out.println("userId1:" + userId1);
	}
}
